#include "at_init.hpp"

void usb_clock48m_select(usb_clk48_s clk_s);
void RTOS_TaskCreate();
static void dma_config(void);
static void adc_config(void);
static void dac_config(void);
static void gpio_config(void);
static void tmr_config(void);
usbd_core_type usb_core_dev;

void init()
{
    __set_PRIMASK(1);
    nvic_priority_group_config(NVIC_PRIORITY_GROUP_4);
    system_clock_config();
    delay_init();
    uart_print_init(921600);
    usb_clock48m_select(USB_CLK_HICK);
    crr_periph_clock_enable(CRR_USB_PERIPH_CLOCK, TRUE);
    nvic_irq_enable(USBFS_L_CAN1_RX0_IRQn, 1, 0);
    /* usb core init */
    usbd_core_init(&usb_core_dev, USB, &custom_hid_class_handler, &custom_hid_desc_handler, 0);
    /* enable usb pull-up */
    usbd_connect(&usb_core_dev);
    gpio_config();
    adc_config();
    dac_config();
    dma_config();
    tmr_config();
    adc_enable(ADC1, TRUE);
    // delay_ms(1000);
    // usb_flag_get
}

void usb_clock48m_select(usb_clk48_s clk_s)
{
    if (clk_s == USB_CLK_HICK)
    {
        crr_usb_clock_source_select(CRR_USB_CLOCK_SOURCE_HICK);

        /* enable the acc calibration ready interrupt */
        crr_periph_clock_enable(CRR_ACC_PERIPH_CLOCK, TRUE);

        /* update the c1\c2\c3 value */
        acc_write_c1(7980);
        acc_write_c2(8000);
        acc_write_c3(8020);

        /* open acc calibration */
        acc_calibration_mode_enable(ACC_CAL_HICKTRIM, TRUE);
    }
    else
    {
        switch (system_core_clock)
        {
        /* 48MHz */
        case 48000000:
            crr_usb_clock_div_set(CRR_USB_DIV_1);
            break;

        /* 72MHz */
        case 72000000:
            crr_usb_clock_div_set(CRR_USB_DIV_1_5);
            break;

        /* 96MHz */
        case 96000000:
            crr_usb_clock_div_set(CRR_USB_DIV_2);
            break;

        /* 120MHz */
        case 120000000:
            crr_usb_clock_div_set(CRR_USB_DIV_2_5);
            break;

        /* 144MHz */
        case 144000000:
            crr_usb_clock_div_set(CRR_USB_DIV_3);
            break;

        /* 168MHz */
        case 168000000:
            crr_usb_clock_div_set(CRR_USB_DIV_3_5);
            break;

        /* 192MHz */
        case 192000000:
            crr_usb_clock_div_set(CRR_USB_DIV_4);
            break;

        default:
            break;
        }
    }
}

extern "C" void USBFS_L_CAN1_RX0_IRQHandler(void)
{
    usbd_irq_handler(&usb_core_dev);
    // printf("?\n");
}
uint16_t TxBuf[AXIS_BUFFER][4];
static void dma_config(void)
{
    dma_init_type dma_init_struct;
    crr_periph_clock_enable(CRR_DMA1_PERIPH_CLOCK, TRUE);
    dma_reset(DMA1_CHANNEL1);
    dma_default_para_init(&dma_init_struct);
    dma_init_struct.buffer_size = 40;
    dma_init_struct.direction = DMA_DIR_PERIPHERAL_TO_MEMORY;
    dma_init_struct.memory_base_addr = (uint32_t)&TxBuf;
    dma_init_struct.memory_data_width = DMA_MEMORY_DATA_WIDTH_HALFWORD;
    dma_init_struct.memory_inc_enable = TRUE;
    dma_init_struct.peripheral_base_addr = (uint32_t) & (ADC1->odt);
    dma_init_struct.peripheral_data_width = DMA_PERIPHERAL_DATA_WIDTH_HALFWORD;
    dma_init_struct.peripheral_inc_enable = FALSE;
    dma_init_struct.priority = DMA_PRIORITY_HIGH;
    dma_init_struct.loop_mode_enable = TRUE;
    dma_init(DMA1_CHANNEL1, &dma_init_struct);

    dma_channel_enable(DMA1_CHANNEL1, TRUE);
}

static void gpio_config(void)
{
    gpio_init_type gpio_initstructure;
    crr_periph_clock_enable(CRR_GPIOA_PERIPH_CLOCK, TRUE);
    crr_periph_clock_enable(CRR_GPIOB_PERIPH_CLOCK, TRUE);
    crr_periph_clock_enable(CRR_GPIOC_PERIPH_CLOCK, TRUE);
    crr_periph_clock_enable(CRR_GPIOD_PERIPH_CLOCK, TRUE);
    gpio_default_para_init(&gpio_initstructure);
    //  ADC 通道 0、1、2
    gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
    gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_2;
    gpio_init(GPIOA, &gpio_initstructure);
    //  ADC 通道 10、11、12、13
    gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1 | GPIO_PINS_2 | GPIO_PINS_3;
    gpio_init(GPIOC, &gpio_initstructure);
    // DAC 通道2
    gpio_initstructure.gpio_pins = GPIO_PINS_4;
    gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
    gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_STRONGER;
    gpio_init(GPIOA, &gpio_initstructure);
    // TIM8 刹车
    gpio_initstructure.gpio_mode = GPIO_MODE_INPUT;
    gpio_initstructure.gpio_pins = GPIO_PINS_6;
    gpio_initstructure.gpio_pull = GPIO_PULL_DOWN;
    gpio_init(GPIOA, &gpio_initstructure);
    //五向按钮 右
    gpio_initstructure.gpio_mode = GPIO_MODE_INPUT;
    gpio_initstructure.gpio_pins = GPIO_PINS_15;
    gpio_initstructure.gpio_pull = GPIO_PULL_UP;
    gpio_init(GPIOA, &gpio_initstructure);
    //五向按钮 上 左 中
    gpio_initstructure.gpio_pins = GPIO_PINS_10 | GPIO_PINS_11 | GPIO_PINS_12;
    gpio_init(GPIOC, &gpio_initstructure);
    //五向按钮 下
    gpio_initstructure.gpio_pins = GPIO_PINS_2;
    gpio_init(GPIOD, &gpio_initstructure);
    // TIM8_PWM 通道 1、2、3
    gpio_initstructure.gpio_mode = GPIO_MODE_MUX;
    gpio_initstructure.gpio_out_type = GPIO_OUTPUT_PUSH_PULL;
    gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
    gpio_initstructure.gpio_drive_strength = GPIO_DRIVE_STRENGTH_MODERATE;
    gpio_initstructure.gpio_pins = GPIO_PINS_6 | GPIO_PINS_7 | GPIO_PINS_8;
    gpio_init(GPIOC, &gpio_initstructure);
    // TIM8_PWM 互补通道 1
    gpio_initstructure.gpio_pins = GPIO_PINS_7; // | GPIO_PINS_8 | GPIO_PINS_9 | GPIO_PINS_10;
    gpio_init(GPIOA, &gpio_initstructure);
    // TIM8_PWM 互补通道 2、3
    gpio_initstructure.gpio_pins = GPIO_PINS_0 | GPIO_PINS_1;
    gpio_init(GPIOB, &gpio_initstructure);
    // TIM1 编码器模式 CC1-A CC2-B CC3-Z
    // gpio_initstructure.gpio_mode = GPIO_MODE_ANALOG;
    // gpio_initstructure.gpio_pull = GPIO_PULL_NONE;
    // gpio_initstructure.gpio_pins = GPIO_PINS_8 | GPIO_PINS_9 | GPIO_PINS_10;
    // gpio_init(GPIOA, &gpio_initstructure);
}

static void adc_config(void)
{
    adc_base_config_type adc_base_struct;
    crr_periph_clock_enable(CRR_ADC1_PERIPH_CLOCK, TRUE);
    crr_periph_clock_enable(CRR_IOMUX_PERIPH_CLOCK, TRUE);
    /* select combine mode */
    adc_combine_mode_select(ADC_INDEPENDENT_MODE);
    adc_base_default_para_init(&adc_base_struct);
    adc_base_struct.sequence_mode = TRUE;
    adc_base_struct.repeat_mode = TRUE;
    adc_base_struct.data_align = ADC_RIGHT_ALIGNMENT;
    adc_base_struct.ordinary_channel_length = 4;
    adc_base_config(ADC1, &adc_base_struct);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_13, 1, ADC_SAMPLETIME_55_5);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_0, 2, ADC_SAMPLETIME_55_5);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_1, 3, ADC_SAMPLETIME_55_5);
    adc_ordinary_channel_set(ADC1, ADC_CHANNEL_2, 4, ADC_SAMPLETIME_55_5);
    adc_ordinary_conversion_trigger_set(ADC1, ADC12_ORDINARY_TRIG_SOFTWARE, TRUE);

    adc_preempt_channel_length_set(ADC1, 3);
    adc_preempt_channel_set(ADC1, ADC_CHANNEL_10, 1, ADC_SAMPLETIME_55_5);
    adc_preempt_channel_set(ADC1, ADC_CHANNEL_11, 2, ADC_SAMPLETIME_55_5);
    adc_preempt_channel_set(ADC1, ADC_CHANNEL_12, 3, ADC_SAMPLETIME_55_5);
    adc_preempt_conversion_trigger_set(ADC1, ADC12_PREEMPT_TRIG_EXINT15_TMR8CH4, TRUE);
    adc_preempt_offset_value_set(ADC1, ADC_PREEMPT_CHANNEL_1, 2048);
    adc_preempt_offset_value_set(ADC1, ADC_PREEMPT_CHANNEL_2, 2048);
    adc_preempt_offset_value_set(ADC1, ADC_PREEMPT_CHANNEL_3, 2048);
    // adc_preempt_auto_mode_enable(ADC1, TRUE);
    gpio_pin_remap_config(ADC1_ETP_GMUX, TRUE);
    adc_dma_mode_enable(ADC1, TRUE);
    adc_enable(ADC1, TRUE);
    adc_calibration_init(ADC1);
    while (adc_calibration_init_status_get(ADC1))
        ;
    adc_calibration_start(ADC1);
    while (adc_calibration_status_get(ADC1))
        ;
}
static void dac_config(void)
{
    crr_periph_clock_enable(CRR_DAC_PERIPH_CLOCK, TRUE);
    // dac_trigger_select(DAC1_SELECT, DAC_SOFTWARE_TRIGGER);
    dac_trigger_enable(DAC1_SELECT, FALSE);
    dac_wave_generate(DAC1_SELECT, DAC_WAVE_GENERATE_NONE);
    dac_mask_amplitude_select(DAC1_SELECT, DAC_LSFR_BITB0_AMPLITUDE_4095);
    dac_output_buffer_enable(DAC1_SELECT, FALSE);
    dac_enable(DAC1_SELECT, TRUE);
    dac_1_data_set(DAC1_12BIT_RIGHT,0);
}
static void tmr_config(void)
{
    tmr_output_config_type tmr_output_struct;
    tmr_input_config_type tmr_input_config_struct;
    crr_clocks_freq_type crr_clocks_freq_struct = {0};

    crr_periph_clock_enable(CRR_TMR8_PERIPH_CLOCK, TRUE);

    crr_clocks_freq_get(&crr_clocks_freq_struct);
    /* compute the value to be set in arr regiter to generate signal frequency at 17.57 khz */
    uint16_t timer_period = (crr_clocks_freq_struct.sclk_freq / 2 / 15000);

    tmr_base_init(TMR8, 8000, 0);
    tmr_cnt_dir_set(TMR8, TMR_COUNT_TWO_WAY_3);
    tmr_clock_source_div_set(TMR8, TMR_CLOCK_DIV1);
    tmr_repetition_counter_set(TMR8, 2);
    tmr_output_default_para_init(&tmr_output_struct);
    tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_B;
    tmr_output_struct.oc_output_state = TRUE;
    tmr_output_struct.oc_polarity = TMR_OUTPUT_ACTIVE_HIGH;
    tmr_output_struct.oc_idle_state = TRUE;
    tmr_output_struct.occ_output_state = TRUE;
    tmr_output_struct.occ_polarity = TMR_OUTPUT_ACTIVE_HIGH;
    tmr_output_struct.occ_idle_state = TRUE;
    /* channel 1 */
    tmr_output_channel_config(TMR8, TMR_SELECT_CHANNEL_1, &tmr_output_struct);
    tmr_channel_value_set(TMR8, TMR_SELECT_CHANNEL_1, 0);

    /* channel 2 */
    tmr_output_channel_config(TMR8, TMR_SELECT_CHANNEL_2, &tmr_output_struct);
    tmr_channel_value_set(TMR8, TMR_SELECT_CHANNEL_2, 0);

    /* channel 3 */
    tmr_output_channel_config(TMR8, TMR_SELECT_CHANNEL_3, &tmr_output_struct);
    tmr_channel_value_set(TMR8, TMR_SELECT_CHANNEL_3, 0);

    /* channel 4 */
    tmr_output_struct.oc_mode = TMR_OUTPUT_CONTROL_PWM_MODE_A;
    tmr_output_channel_config(TMR8, TMR_SELECT_CHANNEL_4, &tmr_output_struct);
    tmr_channel_value_set(TMR8, TMR_SELECT_CHANNEL_4, 100);

    /* output enable */
    tmr_output_enable(TMR8, TRUE);
    /* enable tmr1 */
    tmr_counter_enable(TMR8, TRUE);
}